#include <sys/types.h>         
#include <sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<iostream>
#include"Log.hpp"

enum{
    SocketErr=1,
    BindErr,
    ListenErr,
    AcceptErr,
};

const int backlog=10;
class Sock
{
public:
    Sock()
    {}
    ~Sock()
    {}
public:
    void Socket()
    {
        sockfd_=socket(AF_INET, SOCK_STREAM,0);
        if(sockfd_<0)
        {
            lg(Fatal,"socket faill,exit:%d,strerror:%s",errno,strerror(errno));
            exit(SocketErr);
        }
    }
    void Bind(uint16_t port){
        sockaddr_in local;
        local.sin_port=htons(port);
        local.sin_family=AF_INET;
        local.sin_addr.s_addr=INADDR_ANY;
        socklen_t len=sizeof(local);
        int n=bind(sockfd_,(sockaddr*)(&local),len);
        if(n<0){
            lg(Fatal,"bind erron,%d:%s",errno,strerror(errno));
            exit(BindErr);
        }
    }
    void Listen(){
        int n=listen(sockfd_,backlog);
        if(n<0){
            lg(Fatal,"bind erron,%d:%s",errno,strerror(errno));
            exit(ListenErr);
            }
    }
    int Accept(string*clientip,uint16_t*clientport)
    {
        int newfd;
        sockaddr_in sock;
        sock.sin_family=AF_INET;
        socklen_t len=sizeof(sock);
        newfd=accept(sockfd_,(sockaddr*)(&sock),&len);
        if(sockfd_<0){
            lg(Warning,"accept erron,%d:%s",errno,strerror(errno));//接收不到人来连接就一直接收
            return -1;
        }
        char buf[124];
        *clientport=ntohs(sock.sin_port);
        inet_ntop(AF_INET,&(sock.sin_addr),buf,sizeof(sock));
        *clientip=buf;
        return newfd;
    }
    bool Connect(uint16_t port,const string& ip)
    {
        sockaddr_in sock;
        sock.sin_family=AF_INET;
        sock.sin_port=htons(port);
        inet_aton(ip.c_str(),&(sock.sin_addr));
        if(connect(sockfd_,(sockaddr*)(&sock),sizeof(sock))<0){
            std::cerr << "connect to " << ip << ":" << port << " error" << std::endl;
            return false;
        }
        return true;
    }
    void Close()
    {
        close(sockfd_);
    }
    int Fd()
    {
        return sockfd_;
    }
private:
    int sockfd_;
};